<?php

namespace App\Http\Controllers\Api;

use App\Constant;
use App\Enums\AvailableStatus;
use App\Enums\ProductStatus;
use App\Enums\ProductType;
use App\Exceptions\ApiException;
use App\Http\Controllers\Controller;
use App\Models\Asset;
use App\Models\BlindBoxProduct;
use App\Models\FrontendUser;
use App\Models\Product;
use App\Models\ProductCategory;
use App\Models\ProductConfig;
use App\Models\ProductToken;
use App\Models\PurchaseWhiteList;
use App\Services\ProductService;
use App\Services\SettingService;
use App\Services\WalletService;
use Carbon\Carbon;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Auth;

class ProductController extends Controller
{
    /** @var ProductService */
    private $productService;

    /** @var WalletService */
    private $walletService;

    /** @var SettingService */
    private $settingService;

    /**
     * ProductController constructor.
     */
    public function __construct(
        ProductService $productService,
        WalletService $walletService,
        SettingService $settingService
    ) {
        $this->productService = $productService;
        $this->walletService = $walletService;
        $this->settingService = $settingService;
    }

    /** 查询商品类别 */
    public function listCategories()
    {
        return $this->productService->getCategoryTree(request()->agent_id);
    }

    /** 查询商品列表 */
    public function listProducts()
    {
        $page = request()->page ?: 1;
        $limit = request()->limit ?: 10;
        $typeStr = request()->type ?: ProductType::ISSUE;
        $types = explode(',', $typeStr);
        $query = $this->getAgentProductQuery()
            ->with(['category', 'configs'])
            ->where('status', ProductStatus::ON_SALE)
            ->whereIn('type', $types)
            ->when(request()->category_id, function ($q) {
                $categoryId = request()->category_id;
                $category = ProductCategory::query()->find($categoryId);
                if (count($category->children) > 0) {
                    return $q->whereIn('category_id', Arr::pluck($category->children, 'id'));
                }

                return $q->where('category_id', $categoryId);
            })
            ->orderByDesc('sequence')
            ->orderByDesc('id');
        $count = $query->count();
        $products = $query->offset(($page - 1) * $limit)->limit($limit)->get();

        //应用提前购配置
        /** @var FrontendUser $user */
        $user = $this->getAuthUser();
        /** @var PurchaseWhiteList[] $earlyBuies */
        $earlyBuys = [];
        if ($user) {
            $earlyBuys = PurchaseWhiteList::query()
                ->whereIn('product_id', Arr::pluck($products, 'id'))
                ->where('user_mobile', $user->mobile)
                ->where('status', AvailableStatus::ENABLED)
                ->get()
                ->mapWithKeys(function (PurchaseWhiteList $config) {
                    return [$config->product_id => $config];
                });
        }

        $list = $products->map(function (Product $product) use ($earlyBuys) {
            $earlyBuy = Arr::get($earlyBuys, $product->id);
            $arr = [
                'id' => $product->id,
                'category' => $product->category ? $product->category->name : '',
                'type' => $product->type->value,
                'logo_url' => $product->logo_url,
                'product_name' => $product->name,
                'issuer' => $product->issuer,
                'sale_price' => $product->display_price,
                'issue_count' => $product->issue_count,
                'sale_units' => $product->sales_count,
                'left_units' => $product->left_count,
                'show_left_units' => (bool) Arr::get($product->configs->mapWithKeys(function (ProductConfig $config) {
                    return [$config->config_key => $config->config_value];
                }), ProductConfig::SHOW_LEFT_COUNT, 1),
                'start_time' => ($product->start_time ?: $product->online_time)->toDateTimeString(),
            ];
            if ($product->end_time) {
                $arr['end_time'] = $product->end_time->toDateTimeString();
            }
            if ($earlyBuy) {
                if ($product->start_time) {
                    $arr['start_time'] = $product->start_time->subMinutes($earlyBuy->early_buy_minutes)->toDateTimeString();
                }
            }

            return $arr;
        });

        return [
            'list' => $list,
            'count' => $count,
        ];
    }

    /** 查询发售日历 */
    public function getSaleCalendar()
    {
        // 已上架但未开售
        $products = $this->getAgentProductQuery()
            ->with(['category'])
            ->where('status', ProductStatus::ON_SALE)
            ->whereIn('type', [ProductType::ISSUE, ProductType::BLIND_BOX])
            ->where('start_time', '>', now())
            ->orderBy('start_time')
            ->get();

        $result = [];
        foreach ($products as $product) {
            $startTime = Carbon::parse($product->start_time);
            $day = $startTime->format('Y-m-d');
            $time = $startTime->format('H:i');
            $result[$day][$time][] = [
                'id' => $product->id,
                'category' => $product->category ? $product->category->name : '其它',
                'type' => $product->type->value,
                'logo_url' => $product->logo_url,
                'product_name' => $product->name,
                'issuer' => $product->issuer,
                'sale_price' => $product->display_price,
                'left_units' => $product->left_count,
                'start_time' => ($product->start_time ?: $product->online_time)->toDateTimeString(),
            ];
        }

        return $result;
    }

    /** 查询商品详情 */
    public function getProduct($id)
    {
        $product = $this->findProductOrFail($id);
        $isResale = $product->type->is(ProductType::RESALE());
        $onlineTime = $startTime = '';
        if ($product->online_time) {
            $onlineTime = $product->online_time->toDateTimeString();
            if ($product->start_time) {
                $startTime = $product->start_time->toDateTimeString();
            } else {
                $startTime = $onlineTime;
            }
        }

        $result = [
            'id' => $product->id,
            'category' => $product->category ? $product->category->name : '其它',
            'contract_address' => $product->contract_address ?: '',
            'product_name' => $product->name,
            'logo_url' => $product->logo_url,
            'product_intro' => $product->intro,
            'product_detail' => $product->description,
            'sale_price' => $product->display_price,
            'issue_count' => $product->issue_count,
            'sale_units' => $product->sales_count,
            'left_units' => $product->left_count,
            'show_left_units' => (bool) Arr::get($product->configs->mapWithKeys(function (ProductConfig $config) {
                return [$config->config_key => $config->config_value];
            }), ProductConfig::SHOW_LEFT_COUNT, 1),
            'buy_limit' => $product->buy_limit,
            'type' => $product->type->value,
            'online_time' => $onlineTime,
            'start_time' => $startTime,
        ];
        if ($isResale && $product->resale_user) {
            $result['owner'] = hide_mobile($product->resale_user->mobile);
            // 转售商品只有一个token
            $token = ProductToken::query()->where('product_id', $id)->first();
            // 查询转售商品对应的资产
            $asset = Asset::query()
                ->where('user_id', $product->resale_user_id)
                ->where('token_id', $token->token_id)
                ->orderByDesc('id')
                ->first();
            $result['asset_id'] = $asset->id;
        }
        if ($product->end_time) {
            $result['end_time'] = $product->end_time->toDateTimeString();
        }

        //应用提前购配置
        $user = $this->getAuthUser();
        /** @var PurchaseWhiteList $earlyBuy */
        $earlyBuy = null;
        if ($user) {
            $earlyBuy = PurchaseWhiteList::query()
                ->where('product_id', $id)
                ->where('user_mobile', $user->mobile)
                ->where('status', AvailableStatus::ENABLED)
                ->first();
        }

        if ($earlyBuy) {
            $result['buy_limit'] = $earlyBuy->buy_limit;
            if ($product->start_time) {
                $result['start_time'] = $product->start_time->subMinutes($earlyBuy->early_buy_minutes)->toDateTimeString();
            }
        }

        return $result;
    }

    /** 查询肓盒内的商品列表 */
    public function listProductsInBlindBox($blindBoxId)
    {
        return BlindBoxProduct::query()
            ->where('blind_box_id', $blindBoxId)
            ->orderBy('quantity')
            ->get()
            ->map(function (BlindBoxProduct $item) {
                return [
                    'id' => $item->inside_product_id,
                    'name' => $item->product->name,
                    'logo_url' => $item->product->logo_url,
                    'quantity' => $item->quantity,
                ];
            });
    }

    /** 查询作品存证 */
    public function getProductEvidence($id)
    {
        $product = $this->findProductOrFail($id);

        try {
            $evidence = $this->walletService->productEvidence($product->public_hash);
        } catch (\Exception $e) {
            throw new ApiException('存证信息查询失败');
        }

        return [
            'name' => Arr::get($evidence, 'assetsName', ''),
            'category' => Arr::get($evidence, 'assetsCategoryCN', ''),
            'author' => $product->author ?: '',
            'issuer' => $product->issuer,
            'hold_rights' => $product->hold_rights,
            'logo_url' => $product->logo_url,
            'asset_url' => $product->asset_image_url ?: '',
            'issue_count' => intval(Arr::get($evidence, 'issueCount', 0)),
            'cert_sn' => Arr::get($evidence, 'certSN', ''),
            'hash' => Arr::get($evidence, 'hash', ''),
            'create_time' => Arr::get($evidence, 'ptime', ''),
        ];
    }

    private function getAgentProductQuery()
    {
        $query = Product::query()
            ->where('agent_id', request()->agent_id);

        $user = $this->getAuthUser();
        // 如果用户未登录或登录用户不是测试用户，则不显示测试商品
        $testMobiles = $this->settingService->getTestMobiles();
        if (!$user || !in_array($user->mobile, $testMobiles)) {
            $query->where('test_only', false);
        }

        return $query;
    }

    /**
     * @param $id
     *
     * @throws ApiException
     *
     * @return Product
     */
    private function findProductOrFail($id)
    {
        $product = $this->getAgentProductQuery()->find($id);
        if (!$product) {
            throw new ApiException('商品未找到');
        }

        return $product;
    }

    private function getAuthUser()
    {
        /* @var FrontendUser $user */
        return Auth::guard(Constant::GUARD_API)->user();
    }
}
